﻿#if UNITY_EDITOR

using System;
using System.IO;
using UnityEditor;
using UnityEngine;

public static class SpriteTool
{

    //==================== OpenDirAfterExport

    const string PrefsKey_OpenDirAfterExport = "ExportSelectSpriteTool.OpenDirAfterExport";
    const string MenuItemPath_OpenDirAfterExport = "Assets/Image/Open Dir After Export";
    private static int s_OpenSpriteExportDirFlag = -1; //-1_未初始化, 0_false, 1_true

    public static bool IsOpenDirAfterExport
    {
        get
        {
            if (-1 == s_OpenSpriteExportDirFlag)
            {
                s_OpenSpriteExportDirFlag = 1;
                s_OpenSpriteExportDirFlag = EditorPrefs.GetInt(PrefsKey_OpenDirAfterExport, 1); //默认开启
            }
            return 1 == s_OpenSpriteExportDirFlag;
        }
        set
        {
            var newValue = value ? 1 : 0;
            if (s_OpenSpriteExportDirFlag != newValue)
            {
                s_OpenSpriteExportDirFlag = newValue;
                EditorPrefs.SetInt(PrefsKey_OpenDirAfterExport, s_OpenSpriteExportDirFlag);
            }
        }
    }

    [MenuItem(MenuItemPath_OpenDirAfterExport, true)]
    static bool MenuItemInit_IsOpenDirAfterExport()
    {
        Menu.SetChecked(MenuItemPath_OpenDirAfterExport, IsOpenDirAfterExport);
        return true;
    }

    [MenuItem(MenuItemPath_OpenDirAfterExport, false)]
    static void MenuItem_IsOpenDirAfterExport()
    {
        IsOpenDirAfterExport = !Menu.GetChecked(MenuItemPath_OpenDirAfterExport);
    }

    //====================

    //====================

    const string MenuItemPath_PrintSpriteInfo = "Assets/Image/Print Sprite Info";

    [MenuItem(MenuItemPath_PrintSpriteInfo)]
    static void MenuItem_PrintSpriteInfo()
    {
        var sp = Selection.activeObject as Sprite;
        if (null == sp) return;

        Debug.Log($"===== {sp.name}\n");
        Debug.Log($"pack: {sp.packed}, packMode:{sp.packingMode}, rot:{sp.packingRotation}");

        Debug.Log($"texRect: {sp.textureRect.MyToString()}\n");
        Debug.Log($"offset lb: {sp.textureRectOffset.MyToString()}\n");
        var offsetRight = sp.rect.width - (sp.textureRectOffset.x + sp.textureRect.width);
        var offsetTop = sp.rect.height - (sp.textureRectOffset.y + sp.textureRect.height);
        Debug.Log($"offset rt: ({offsetRight}, {offsetTop})\n");
        Debug.Log($"rect: {sp.rect.MyToString()}\n");
        Debug.Log($"border: {sp.border.MyToString()}\n"); //left, bottom, right, top
        Debug.Log($"bounds: {sp.bounds}");

        Debug.Log($"padding: {UnityEngine.Sprites.DataUtility.GetPadding(sp).MyToString()}\n"); //比如:padding-left就是textureRect.x, padding-right就是rect.width - textureRect.width - textureRect.x

        var tex = sp.texture;
        Debug.Log($"sp tex: {tex.name}, {AssetDatabase.GetAssetPath(tex)}\n");

        var uv_o = UnityEngine.Sprites.DataUtility.GetOuterUV(sp);
        Debug.Log($"uv_o: {uv_o.MyToString()}\n");
        Debug.Log($"uv_o: {uv_o.x * tex.width}, {uv_o.y * tex.height}, {uv_o.z * tex.width}, {uv_o.w * tex.height}\n");

        var uv_i = UnityEngine.Sprites.DataUtility.GetInnerUV(sp);
        Debug.Log($"uv_i: {uv_i.MyToString()}\n"); //比如: uv_i.x = uv_o.x - uv_offsetLeft, uv_i.y = uv_o.y - uv_offset_bottom
        Debug.Log($"uv_i: {uv_i.x * tex.width}, {uv_i.y * tex.height}, {uv_i.z * tex.width}, {uv_i.w * tex.height}\n");

        Debug.Log($"minSize: {UnityEngine.Sprites.DataUtility.GetMinSize(sp).MyToString()} "); //比如: x = border.x + border.z

        var assetPath = AssetDatabase.GetAssetPath(sp);
        var imp = AssetImporter.GetAtPath(assetPath) as TextureImporter;
        if (null != imp && TextureImporterType.Sprite == imp.textureType)
        {
            Debug.Log($"packingTag: {imp.spritePackingTag}");
        }
        Debug.Log($"=====");
    }

    static string MyToString(this Vector2 vec2)
    {
        return $"({vec2.x}, {vec2.y})";
    }

    static string MyToString(this Vector3 vec3)
    {
        return $"({vec3.x}, {vec3.y}, {vec3.z})";
    }

    static string MyToString(this Vector4 vec4)
    {
        return $"({vec4.x}, {vec4.y}, {vec4.z}, {vec4.w})";
    }

    static string MyToString(this Rect rect)
    {
        return $"({rect.x}, {rect.y}, {rect.width}, {rect.height})";
    }

    //====================

    //==================== ExportSelectSprite

    const string Output_Dir_Path = "_Temp/ExportSprite/";

    const string MenuItemPath_ExportSelectSprite = "Assets/Image/Export Select Sprite";

    [MenuItem(MenuItemPath_ExportSelectSprite, true)]
    static bool MenuItemValidator_ExportSelectSprite()
    {
        if (Application.isPlaying)
            return false;
        if (null == Selection.activeObject)
            return false;
        var sp = Selection.activeObject as Sprite;
        return null != sp;
    }


    [MenuItem(MenuItemPath_ExportSelectSprite)]
    static void MenuItem_ExportSelectSprite()
    {
        var sp = Selection.activeObject as Sprite;
        if (null == sp) return;

        if (!Directory.Exists(Output_Dir_Path) && null == Directory.CreateDirectory(Output_Dir_Path))
        {
            Debug.LogError($"{Output_Dir_Path} create fail!");
            return;
        }

        var srcTex = sp.texture;
        var srcTempRT = RenderTexture.GetTemporary(srcTex.width, srcTex.height, 0, RenderTextureFormat.Default);
        Graphics.Blit(srcTex, srcTempRT);
        var oldActiveRT = RenderTexture.active;
        RenderTexture.active = srcTempRT;

        OutputSprite(srcTempRT, sp);

        RenderTexture.active = oldActiveRT;
        RenderTexture.ReleaseTemporary(srcTempRT);

        Debug.Log($"finish: {Output_Dir_Path}");
    }

    static void OutputSprite(RenderTexture srcTempRT, Sprite sp)
    {
        Rect rect = sp.rect; //该Rect的width, height为裁掉空白前的宽高
        Vector2 offset = sp.textureRectOffset;
        Rect texRect = sp.textureRect; //该Rect的width, height为裁掉空白后的宽高
        var spriteTex = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGBA32, false);

        var readRect = new Rect(texRect.x,
        srcTempRT.height - (texRect.y + texRect.height), //RenderTexture-(0, 0)为左上角, 要转换成左下角(0, 0)
        texRect.width, texRect.height);
        spriteTex.ReadPixels(readRect, (int)offset.x, (int)offset.y); //Texture2D-(0, 0)为左下角
        spriteTex.Apply();

        var pngBytes = spriteTex.EncodeToPNG();
        var spriteOutPath = Path.Combine(Output_Dir_Path, $"{sp.name}.png");
        File.WriteAllBytes(spriteOutPath, pngBytes);

        if (IsOpenDirAfterExport)
        {
            OpenDirAndSelectFile(Path.GetFullPath(spriteOutPath));
        }
    }

    //====================

    private static void OpenDirAndSelectFile(string fileFullPath)
    {
        var process = new System.Diagnostics.Process();
        var psi = new System.Diagnostics.ProcessStartInfo("Explorer.exe");
        psi.Arguments = $"/Select,{fileFullPath}";
        process.StartInfo = psi;
        try
        {
            process.Start();
        }
        catch (Exception ex)
        {
            Debug.LogError($"{ex.StackTrace}");
        }
        finally
        {
            process.Close();
        }
    }

}

#endif